﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace TomNet.Http
{
    /// <summary>
    /// 通用HttpClient
    /// </summary>
    public class TomNetHttpClient
    {
        private readonly HttpClient _client;

        private readonly ILogger _logger = null;
        private static ILoggerFactory _loggerFactory;

        public static void EnableDebugLog(ILoggerFactory loggerFactory)
        {
            _loggerFactory = loggerFactory;
        }

        public TomNetHttpClient(HttpClient client)
        {
            _client = client;

            if (_loggerFactory != null)
            {
                _logger = _loggerFactory.CreateLogger(GetType());
            }
        }


        #region 发起Get异步请求
        /// <summary>
        /// 发起Get异步请求
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="uri">访问地址</param>
        /// <param name="parameters">地址附带参数</param>
        /// <param name="isThrowException">是否抛出异常</param>
        /// <returns>HttpClientResult<T>类型</returns>
        public async Task<HttpClientResult<T>> GetAsync<T>(
            string uri,
            Dictionary<string, object> parameters = null,
            bool isThrowException = false) where T : class
        {
            try
            {
                var requestUri = InitUrl(uri, parameters);
                using var response = await _client.GetAsync(requestUri);
                var json = await response.Content.ReadAsStringAsync();

                HttpClientResult<T> result = default;

                if (typeof(T) != typeof(string))
                {
                    result = JsonConvert.DeserializeObject<HttpClientResult<T>>(json);
                }
                else
                {
                    if (json == "")
                        return null;
                    result = new HttpClientResult<T>
                    {
                        Body = json as T
                    };
                }

                if (result != null)
                {
                    result.HttpStatus = response.StatusCode;
                }
                return result;
            }
            catch (Exception e)
            {
                _logger?.Log(LogLevel.Error, e.Message);

                if (isThrowException == true)
                {
                    throw e;
                }
                else
                {
                    return null;
                }
            }
        }
        #endregion 

        #region 发起Delete异步请求
        /// <summary>
        /// 发起Delete异步请求
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="uri">访问地址</param>
        /// <param name="parameters">地址附带参数</param>
        /// <param name="isThrowException">是否抛出异常</param>
        /// <returns>HttpClientResult<T>类型</returns>
        public async Task<HttpClientResult<T>> DeleteAsync<T>(
           string uri,
           Dictionary<string, object> parameters = null,
           bool isThrowException = false) where T : class
        {
            try
            {
                var requestUri = InitUrl(uri, parameters);
                using var response = await _client.DeleteAsync(requestUri);
                var json = await response.Content.ReadAsStringAsync();

                HttpClientResult<T> result = default;


                if (typeof(T) != typeof(string))
                {
                    result = JsonConvert.DeserializeObject<HttpClientResult<T>>(json);
                }
                else
                {
                    if (json == "")
                        return null;
                    result = new HttpClientResult<T>
                    {
                        Body = json as T
                    };
                }

                if (result != null)
                {
                    result.HttpStatus = response.StatusCode;
                }

                return result;
            }
            catch (Exception e)
            {
                _logger?.Log(LogLevel.Error, e.Message);

                if (isThrowException == true)
                {
                    throw e;
                }
                else
                {
                    return null;
                }
            }
        }
        #endregion 

        #region 发起Put异步请求
        /// <summary>
        /// 发起Put异步请求
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="uri">访问地址</param>
        /// <param name="parameters">地址附带参数</param>
        /// <param name="body">Post请求的Body数据</param>
        /// <returns>HttpClientResult<T>类型</returns>
        public async Task<HttpClientResult<T>> PutAsync<T>(
            string uri,
            Dictionary<string, object> parameters,
            object body,
            bool isThrowException = false) where T : class
        {
            try
            {
                var requestUri = InitUrl(uri, parameters);

                using var response = await _client.PutAsync(requestUri, new JsonContent(body));
                var json = await response.Content.ReadAsStringAsync();


                HttpClientResult<T> result = default;


                if (typeof(T) != typeof(string))
                {
                    result = JsonConvert.DeserializeObject<HttpClientResult<T>>(json);
                }
                else
                {
                    if (json == "")
                        return null;
                    result = new HttpClientResult<T>
                    {
                        Body = json as T
                    };
                }

                if (result != null)
                {
                    result.HttpStatus = response.StatusCode;
                }
                return result;
            }
            catch (Exception e)
            {
                _logger?.Log(LogLevel.Error, e.Message);

                if (isThrowException == true)
                {
                    throw e;
                }
                else
                {
                    return null;
                }
            }
        }
        #endregion

        #region 发起POST异步请求
        /// <summary>
        /// 发起POST异步请求
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="uri">访问地址</param>
        /// <param name="parameters">地址附带参数</param>
        /// <param name="body">Post请求的Body数据</param>
        /// <returns>HttpClientResult<T>类型</returns>
        public async Task<HttpClientResult<T>> PostAsync<T>(
            string uri,
            Dictionary<string, object> parameters,
            object body,
            bool isThrowException = false) where T : class
        {
            try
            {
                var requestUri = InitUrl(uri, parameters);
                using var response = await _client.PostAsync(requestUri, new JsonContent(body));
                var json = await response.Content.ReadAsStringAsync();


                HttpClientResult<T> result = default;

                if (typeof(T) != typeof(string))
                {
                    result = JsonConvert.DeserializeObject<HttpClientResult<T>>(json);
                }
                else
                {
                    if (json == "")
                        return null;
                    result = new HttpClientResult<T>
                    {
                        Body = json as T
                    };
                }

                if (result != null)
                {
                    result.HttpStatus = response.StatusCode;
                }
                return result;
            }
            catch (Exception e)
            {
                _logger?.Log(LogLevel.Error, e.Message);

                if (isThrowException == true)
                {
                    throw e;
                }
                else
                {
                    return null;
                }
            }
        }
        #endregion 

        /// <summary>
        /// 初始化URI参数
        /// </summary>
        private string InitUrl(string uri, Dictionary<string, object> parameters)
        {
            if (parameters != null)
            {
                foreach (var kvp in parameters)
                {
                    uri = uri.Replace("{" + kvp.Key + "}", kvp.Value.ToString());
                }
            }
            return uri;
        }


        /// <summary>
        /// 设置Header头信息
        /// </summary>
        public void SetHeaders(Dictionary<string, string> heaaders)
        {
            foreach (var temp in heaaders)
            {
                SetHeaders(temp.Key, temp.Value);
            }
        }

        /// <summary>
        /// 设置Header头信息
        /// </summary>
        public void SetHeaders(string name, string value)
        {
            var headers = _client.DefaultRequestHeaders;
            if (headers.Contains(name))
            {
                headers.Remove(name);
            }

            try
            {
                headers.Add(name, value);
            }
            catch (FormatException)
            {
                headers.TryAddWithoutValidation(name, value);
            }
        }

        /// <summary>
        /// 通过Http请求获取图片字节流，以及图片类型
        /// </summary>
        /// <param name="uri">图片的URI</param>
        /// <returns>Item1：结果标识；Item2：图片类型；Item3：字节流</returns>
        //public async Task<(bool, string, byte[])> GetImageAsync(string uri)
        //{
        //    var bytes = await _client.GetByteArrayAsync(uri);
        //    var ext = ImageValidate.ImageValidateByStream(bytes);
        //    //string image = "";
        //    //if (ext.Item1)
        //    //{
        //    //    image = Convert.ToBase64String(bytes);
        //    //}
        //    var contentType = ImageValidate.GetImageType(ext.Item2);
        //    return (ext.Item1, contentType, bytes);
        //}
    }
}
